﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Electrical;
using Autodesk.Revit.UI;
using YArchitech.Revit;
using YArchitech.Revit.Electric;

namespace HYRElectric.PowerSystem
{
	[Regeneration(RegenerationOption.Manual)]
	[Transaction(TransactionMode.Manual)]
	public class CreateSystem : IExternalCommand
	{
		public Result Execute(ExternalCommandData cmdData, ref string message, ElementSet elements)
		{
			this.doc = cmdData.Application.ActiveUIDocument.ActiveView.Document;
			Transaction transaction = new Transaction(this.doc, "hy");
			transaction.Start();
			Result result;
			using (this.dlgSys = new DlgPowerSys())
			{
				this.dlgSys.DialogResult = this.dlgSys.ShowDialog();
				if (this.dlgSys.DialogResult == DialogResult.Cancel)
				{
					transaction.RollBack();
					result = Autodesk.Revit.UI.Result.Cancelled;
				}
				else
				{
					if (this.dlgSys.DialogResult == DialogResult.OK)
					{
						this.DeleteAllElectricalSys();
						this.numberPrefix = this.dlgSys.txtNumberPrefix.Text.Trim();
						this.delimiter = this.dlgSys.txtDelimiter.Text.Trim();
						if (this.dlgSys.rdoWithPanel.Checked)
						{
							this.isWithPanel = true;
						}
						else
						{
							this.isWithPanel = false;
							this.powerPrefix = this.dlgSys.txtPowerPrefix.Text;
						}
						ICollection<Element> allPanel = this.GetAllPanel();
						if (this.dlgSys.rdoUniformNumber.Checked)
						{
							this.numPrefix = this.numberPrefix;
							if (allPanel.Count > 0)
							{
								this.CreatePanelSystemByPanel(allPanel);
							}
						}
						else
						{
							int num = 0;
							List<Element> list = new FilteredElementCollector(this.doc).OfClass(typeof(Level)).ToList<Element>();
							for (int i = 0; i < list.Count - 1; i++)
							{
								for (int j = 0; j < list.Count - 1 - i; j++)
								{
									if (Convert.ToDouble(list[j].get_Parameter(BuiltInParameter.LEVEL_ELEV).AsValueString()) > Convert.ToDouble(list[j + 1].get_Parameter(BuiltInParameter.LEVEL_ELEV).AsValueString()))
									{
										Element value = list[j];
										list[j] = list[j + 1];
										list[j + 1] = value;
									}
								}
							}
							foreach (Element element in list)
							{
								num++;
								if (this.dlgSys.rdoNumberAgo.Checked)
								{
									this.numPrefix = num + this.numberPrefix;
								}
								else
								{
									this.numPrefix = this.numberPrefix + num;
								}
								List<Element> list2 = new List<Element>();
								foreach (Element element2 in allPanel)
								{
									if (element2 != null)
									{
										try
										{
											if (element2.get_Parameter(BuiltInParameter.FAMILY_LEVEL_PARAM) != null && element2.get_Parameter(BuiltInParameter.FAMILY_LEVEL_PARAM).AsElementId() == element.Id)
											{
												list2.Add(element2);
											}
											else if (element2.get_Parameter(BuiltInParameter.INSTANCE_SCHEDULE_ONLY_LEVEL_PARAM) != null && element2.get_Parameter(BuiltInParameter.INSTANCE_SCHEDULE_ONLY_LEVEL_PARAM).AsElementId() == element.Id)
											{
												list2.Add(element2);
											}
										}
										catch (Exception)
										{
										}
									}
								}
								if (list2.Count > 0)
								{
									this.CreatePanelSystemByPanel(list2);
								}
							}
						}
					}
					this.PromptInformation();
					transaction.Commit();
					result = Autodesk.Revit.UI.Result.Succeeded;
				}
			}
			return result;
		}

		private void CreatePanelSystemByPanel(ICollection<Element> allPanel)
		{
			this.panelIndex = 0;
			foreach (Element element in allPanel)
			{
				if (!this.RemoveDuplicatesPanels(element))
				{
					List<Wire> allWireByPanel = this.GetAllWireByPanel(element);
					if (allWireByPanel.Count != 0)
					{
						List<ElementId> currentPanelFirstNodeEquipment = this.GetCurrentPanelFirstNodeEquipment(element, allWireByPanel);
						if (currentPanelFirstNodeEquipment.Count > 0)
						{
							this.SetPanelName(element);
							foreach (ElementId elementId in currentPanelFirstNodeEquipment)
							{
								List<ElementId> list = new List<ElementId>();
								list.Add(elementId);
								Element nodePanel = null;
								if (this.doc.GetElementById(elementId).Category.Id.IntegerValue.ToString() == "OST_ElectricalEquipment")
								{
									nodePanel = this.doc.GetElementById(elementId);
								}
								this.StructureElectricalSystem(element, nodePanel, elementId, list);
							}
						}
					}
				}
			}
		}

		private void SetPanelName(Element panel)
		{
			if (this.dlgSys.rdoRenumbered.Checked)
			{
				this.panelIndex++;
				panel.get_Parameter(BuiltInParameter.RBS_ELEC_PANEL_NAME).Set(this.numPrefix + this.panelIndex.ToString());
				return;
			}
			if (string.IsNullOrEmpty(panel.get_Parameter(BuiltInParameter.RBS_ELEC_PANEL_NAME).AsString()))
			{
				this.panelIndex++;
				panel.get_Parameter(BuiltInParameter.RBS_ELEC_PANEL_NAME).Set(this.numPrefix + this.panelIndex.ToString());
			}
			if (panel.get_Parameter(BuiltInParameter.RBS_ELEC_CIRCUIT_NAMING).AsInteger() == 2)
			{
				panel.get_Parameter(BuiltInParameter.RBS_ELEC_CIRCUIT_PREFIX_SEPARATOR).Set(this.delimiter);
				return;
			}
			if (panel.get_Parameter(BuiltInParameter.RBS_ELEC_CIRCUIT_NAMING).AsInteger() == 0)
			{
				panel.get_Parameter(BuiltInParameter.RBS_ELEC_CIRCUIT_NAMING).Set(0);
				if (string.IsNullOrEmpty(panel.get_Parameter(BuiltInParameter.RBS_ELEC_CIRCUIT_PREFIX).AsString()))
				{
					if (this.isWithPanel)
					{
						panel.get_Parameter(BuiltInParameter.RBS_ELEC_CIRCUIT_PREFIX).Set(this.numPrefix + this.panelIndex.ToString());
					}
					else
					{
						panel.get_Parameter(BuiltInParameter.RBS_ELEC_CIRCUIT_PREFIX).Set(this.powerPrefix);
					}
				}
				panel.get_Parameter(BuiltInParameter.RBS_ELEC_CIRCUIT_PREFIX_SEPARATOR).Set(this.delimiter);
			}
		}

		private void SetSystemName(FamilyInstance panel)
		{
			if (this.isWithPanel)
			{
				if (this.dlgSys.rdoRenumbered.Checked)
				{
					panel.get_Parameter(BuiltInParameter.RBS_ELEC_CIRCUIT_NAMING).Set(2);
					panel.get_Parameter(BuiltInParameter.RBS_ELEC_CIRCUIT_PREFIX_SEPARATOR).Set(this.delimiter);
					return;
				}
			}
			else if (this.dlgSys.rdoRenumbered.Checked)
			{
				panel.get_Parameter(BuiltInParameter.RBS_ELEC_CIRCUIT_NAMING).Set(0);
				panel.get_Parameter(BuiltInParameter.RBS_ELEC_CIRCUIT_PREFIX).Set(this.powerPrefix);
				panel.get_Parameter(BuiltInParameter.RBS_ELEC_CIRCUIT_PREFIX_SEPARATOR).Set(this.delimiter);
			}
		}

		private void PromptInformation()
		{
			string text = "";
			foreach (string text2 in this.successMessage.Keys)
			{
				text = string.Concat(new object[]
				{
					text,
					"配电箱",
					text2,
					"下成功生成",
					this.successMessage[text2],
					"个电力系统\n"
				});
			}
			if (this.errorMessage > 0)
			{
				text = string.Concat(new object[]
				{
					text,
					"没有制定配电箱的电气系统为：",
					this.errorMessage,
					"个"
				});
			}
			if (!string.IsNullOrEmpty(text))
			{
				MessageBox.Show(text, "盈建科提示");
				return;
			}
			MessageBox.Show("该项目不具备构造电气系统的条件！", "盈建科提示");
		}

		private void StructureElectricalSystem(Element currentPanel, Element nodePanel, ElementId currentEquipmentId, List<ElementId> equipmentIdList)
		{
			List<ElementId> list = new List<ElementId>();
			foreach (ElementId eleId in equipmentIdList)
			{
				Connector deviceConnector = this.GetDeviceConnector(eleId);
				foreach (Connector connector in new List<Connector>
				{
					deviceConnector
				})
				{
					ConnectorSet allRefs = connector.AllRefs;
					if (allRefs.Size > 0)
					{
						foreach (object obj in allRefs)
						{
							Element owner = ((Connector)obj).Owner;
							if (owner is Wire)
							{
								Wire wire = owner as Wire;
								foreach (Connector connector2 in this.GetWireConnector(wire))
								{
									ConnectorSet allRefs2 = connector2.AllRefs;
									if (allRefs2.Size > 0)
									{
										foreach (object obj2 in allRefs2)
										{
											Element owner2 = ((Connector)obj2).Owner;
											if (owner2.Id != currentPanel.Id && owner2.Id != currentEquipmentId && owner2 is FamilyInstance && this.GetDeviceConnector(owner2.Id) != null)
											{
												if (!equipmentIdList.Contains(owner2.Id))
												{
													list.Add(owner2.Id);
												}
												if (owner2.Category.Id.IntegerValue.ToString() == "OST_ElectricalEquipment")
												{
													this.nextNodePanel.Add(owner2);
												}
											}
										}
									}
								}
							}
						}
					}
				}
			}
			if (list.Count<ElementId>() > 0)
			{
				foreach (ElementId item in list)
				{
					if (!equipmentIdList.Contains(item))
					{
						equipmentIdList.Add(item);
					}
				}
				this.StructureElectricalSystem(currentPanel, nodePanel, currentEquipmentId, equipmentIdList);
				return;
			}
			if (nodePanel == null)
			{
				this.CreatePanelSystem(equipmentIdList, currentPanel, false);
				return;
			}
			this.SetPanelName(nodePanel);
			if (equipmentIdList.Count == 1)
			{
				this.CreatePanelSystem(equipmentIdList, currentPanel, false);
				return;
			}
			ElementId item2 = null;
			foreach (ElementId elementId in equipmentIdList)
			{
				if (elementId == nodePanel.Id)
				{
					item2 = elementId;
					break;
				}
			}
			equipmentIdList.Remove(item2);
			this.CreatePanelSystem(equipmentIdList, nodePanel, true);
			this.CreatePanelSystem(new List<ElementId>
			{
				nodePanel.Id
			}, currentPanel, false);
		}

		private void CreatePanelSystem(List<ElementId> allPanelEquipment, Element currentPanel, bool isChild)
		{
			FamilyInstance familyInstance = currentPanel as FamilyInstance;
			ElementSet elementSet = new ElementSet();
			foreach (ElementId elementId in allPanelEquipment)
			{
				Element elementById = this.doc.GetElementById(elementId);
				elementSet.Insert(elementById);
			}
			ElectricalSystem electricalSystem = null;
			try
			{
                electricalSystem = this.doc.CreateHyElectricalSystem(elementSet, (Autodesk.Revit.DB.Electrical.ElectricalSystemType)6);
				ElectricSystemCommand.AddShardParameters(this.doc, familyInstance, electricalSystem);
			}
			catch (Exception)
			{
				return;
			}
			try
			{
				if ((familyInstance.MEPModel as ElectricalEquipment).DistributionSystem == null)
				{
					DistributionSysType panelDistributionSysType = this.GetPanelDistributionSysType(familyInstance);
					if (panelDistributionSysType == null)
					{
						this.errorMessage++;
						return;
					}
					familyInstance.get_Parameter(BuiltInParameter.RBS_FAMILY_CONTENT_DISTRIBUTION_SYSTEM).Set(panelDistributionSysType.Id);
					if (!this.successMessage.Keys.Contains(familyInstance.Name))
					{
						this.successMessage.Add(familyInstance.Name, 1);
					}
					else
					{
						this.successMessage[familyInstance.Name] = this.successMessage[familyInstance.Name] + 1;
					}
					electricalSystem.SelectPanel(familyInstance);
				}
				else
				{
					if (!this.successMessage.Keys.Contains(familyInstance.Name))
					{
						this.successMessage.Add(familyInstance.Name, 1);
					}
					else
					{
						this.successMessage[familyInstance.Name] = this.successMessage[familyInstance.Name] + 1;
					}
					electricalSystem.SelectPanel(familyInstance);
				}
				this.SetSystemName(familyInstance);
			}
			catch (Exception)
			{
			}
		}

		private DistributionSysType GetPanelDistributionSysType(FamilyInstance panelFi)
		{
			FamilySymbol elem = this.doc.GetElementById(panelFi.GetTypeId()) as FamilySymbol;
			int num = elem.GetParameter("极数").AsInteger();
			double num2 = elem.GetParameter("额定电压").AsDouble();
			ICollection<Element> allDistributionSysTypeList = this.GetAllDistributionSysTypeList();
			if (allDistributionSysTypeList.Count == 0)
			{
				return null;
			}
			foreach (Element element in allDistributionSysTypeList)
			{
				DistributionSysType distributionSysType = element as DistributionSysType;
				distributionSysType.get_Parameter(BuiltInParameter.RBS_DISTRIBUTIONSYS_PHASE_PARAM).AsInteger();
				try
				{
					if (num != 1)
					{
						if (num == 3)
						{
							ElementId elementId = distributionSysType.get_Parameter(BuiltInParameter.RBS_DISTRIBUTIONSYS_VLL_PARAM).AsElementId();
                            //elementId == null;
							VoltageType voltageType = this.doc.GetElementById(elementId) as VoltageType;
							if (num2 >= voltageType.get_Parameter(BuiltInParameter.RBS_VOLTAGETYPE_MINVOLTAGE_PARAM).AsDouble() && num2 <= voltageType.get_Parameter(BuiltInParameter.RBS_VOLTAGETYPE_MAXVOLTAGE_PARAM).AsDouble())
							{
								return distributionSysType;
							}
						}
					}
					else
					{
						ElementId elementId2 = distributionSysType.get_Parameter(BuiltInParameter.RBS_DISTRIBUTIONSYS_VLG_PARAM).AsElementId();
						if (!(elementId2 == null))
						{
							VoltageType voltageType2 = this.doc.GetElementById(elementId2) as VoltageType;
							if (num2 >= voltageType2.get_Parameter(BuiltInParameter.RBS_VOLTAGETYPE_MINVOLTAGE_PARAM).AsDouble() && num2 <= voltageType2.get_Parameter(BuiltInParameter.RBS_VOLTAGETYPE_MAXVOLTAGE_PARAM).AsDouble())
							{
								return distributionSysType;
							}
						}
					}
				}
				catch (Exception)
				{
				}
			}
			return null;
		}

		private List<ElementId> GetCurrentPanelFirstNodeEquipment(Element panel, List<Wire> wireList)
		{
			List<ElementId> list = new List<ElementId>();
			foreach (Wire wire in wireList)
			{
				List<Connector> wireConnector = this.GetWireConnector(wire);
				if (wireConnector.Count != 0)
				{
					foreach (Connector connector in wireConnector)
					{
						foreach (object obj in connector.AllRefs)
						{
							Element owner = ((Connector)obj).Owner;
							if (!(panel.Id == owner.Id) && owner is FamilyInstance && this.GetDeviceConnector(owner.Id) != null)
							{
								if (owner.Category.Id.IntegerValue.ToString() == "OST_ElectricalEquipment")
								{
									this.firstNodePanelList.Add(owner);
								}
								if (!list.Contains(owner.Id))
								{
									list.Add(owner.Id);
								}
							}
						}
					}
				}
			}
			return list;
		}

		public List<Connector> GetWireConnector(Wire wire)
		{
			List<Connector> list = new List<Connector>();
			ConnectorSetIterator connectorSetIterator = wire.ConnectorManager.Connectors.ForwardIterator();
			while (connectorSetIterator.MoveNext())
			{
				object obj = connectorSetIterator.Current;
				Connector item = obj as Connector;
				list.Add(item);
			}
			return list;
		}

		public Connector GetDeviceConnector(ElementId eleId)
		{
			Connector result = null;
			ConnectorSetIterator connectorSetIterator = (this.doc.GetElementById(eleId) as FamilyInstance).MEPModel.ConnectorManager.Connectors.ForwardIterator();
			while (connectorSetIterator.MoveNext())
			{
				object obj = connectorSetIterator.Current;
				Connector connector = obj as Connector;
				if (connector.Domain == (Autodesk.Revit.DB.Domain)2)
				{
					result = connector;
					break;
				}
			}
			return result;
		}

		private List<Wire> GetAllWireByPanel(Element panel)
		{
			List<Wire> list = new List<Wire>();
			ConnectorSet allRefs = this.GetDeviceConnector(panel.Id).AllRefs;
			if (allRefs.Size > 0)
			{
				foreach (object obj in allRefs)
				{
					Element owner = ((Connector)obj).Owner;
					if (owner is Wire)
					{
						Wire item = owner as Wire;
						list.Add(item);
					}
				}
			}
			return list;
		}

		private void DeleteAllElectricalSys()
		{
			ICollection<Element> allElectricalSystem = this.GetAllElectricalSystem();
			ElementSet elementSet = new ElementSet();
			if (allElectricalSystem.Count > 0)
			{
				foreach (Element element in allElectricalSystem)
				{
					elementSet.Insert(element);
				}
				this.doc.DeleteElement(elementSet);
			}
		}

		private ICollection<Element> GetAllElectricalSystem()
		{
			return new FilteredElementCollector(this.doc).OfClass(typeof(ElectricalSystem)).OfCategory(BuiltInCategory.OST_ElectricalCircuit).ToElements();
		}

		public ICollection<Element> GetAllPanel()
		{
			return new FilteredElementCollector(this.doc).OfClass(typeof(FamilyInstance)).OfCategory(BuiltInCategory.OST_ElectricalEquipment).ToElements();
		}

		public ICollection<Element> GetAllPanelByView(ElementId viewId)
		{
			return new FilteredElementCollector(this.doc, viewId).OfClass(typeof(FamilyInstance)).OfCategory(BuiltInCategory.OST_ElectricalEquipment).ToElements();
		}

		private ICollection<Element> GetViewPlan(Document doc)
		{
			return new FilteredElementCollector(doc).OfClass(typeof(ViewPlan)).ToElements();
		}

		public ICollection<Element> GetAllDistributionSysTypeList()
		{
			return new FilteredElementCollector(this.doc).OfClass(typeof(DistributionSysType)).ToElements();
		}

		private bool RemoveDuplicatesPanels(Element panel)
		{
			bool flag = false;
			if (this.firstNodePanelList.Count > 0)
			{
				using (List<Element>.Enumerator enumerator = this.firstNodePanelList.GetEnumerator())
				{
					while (enumerator.MoveNext())
					{
						if (enumerator.Current.Id == panel.Id)
						{
							flag = true;
							break;
						}
					}
				}
			}
			if (flag)
			{
				return true;
			}
			if (this.nextNodePanel.Count > 0)
			{
				using (List<Element>.Enumerator enumerator = this.nextNodePanel.GetEnumerator())
				{
					while (enumerator.MoveNext())
					{
						if (enumerator.Current.Id == panel.Id)
						{
							flag = true;
							break;
						}
					}
				}
			}
			return flag;
		}

		private List<Element> firstNodePanelList = new List<Element>();

		private List<Element> nextNodePanel = new List<Element>();

		private string delimiter = "";

		private bool isWithPanel = true;

		private string powerPrefix = "";

		private string numberPrefix = "";

		private string numPrefix = "";

		private int panelIndex;

		private DlgPowerSys dlgSys;

		private Dictionary<string, int> successMessage = new Dictionary<string, int>();

		private int errorMessage;

		private Document doc;
	}
}
